package com.huage.courseplatform.application.service.impl;

import com.alibaba.druid.sql.visitor.functions.Now;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.huage.courseplatform.application.mapper.BusinessMapper;
import com.huage.courseplatform.application.mapper.ConfigMapper;
import com.huage.courseplatform.application.mapper.CourseMapper;
import com.huage.courseplatform.application.mapper.PeriodMapper;
import com.huage.courseplatform.application.model.dto.CourseDTO;
import com.huage.courseplatform.application.model.dto.PeriodDTO;
import com.huage.courseplatform.application.model.entity.Business;
import com.huage.courseplatform.application.model.entity.Course;
import com.huage.courseplatform.application.model.entity.Period;
import com.huage.courseplatform.application.model.entity.SysConfig;
import com.huage.courseplatform.application.service.PeriodService;
import com.huage.courseplatform.framework.core.impl.BaseServiceImpl;
import com.huage.courseplatform.framework.model.entity.WxMsgTemplateData;
import com.huage.courseplatform.framework.utils.ApplicationContextUtil;
import com.huage.courseplatform.framework.utils.WechatUtil;
import com.huage.courseplatform.framework.utils.date.DateUtils;
import com.huage.courseplatform.framework.utils.date.LocalDateTimeUtil;
import com.huage.courseplatform.framework.utils.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static com.huage.courseplatform.framework.constant.ConfigConstants.SERVICE_CACHE_HOUR_TIME;

@Service
@Slf4j
public class PeriodServiceImpl extends BaseServiceImpl<PeriodMapper, Period> implements PeriodService {

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    CourseMapper courseMapper;

    @Resource
    PeriodMapper periodMapper;

    @Resource
    ConfigMapper configMapper;


    @Override
    public boolean saveOrUpdate(Period period) {
        return super.saveOrUpdate(period);
    }

    @Override
    public boolean removeById(Serializable id) {
        courseCacheClear((String) id);
        return super.removeById(id);
    }

    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        idList.forEach(id->{
            courseCacheClear((String) id);
        });
        return super.removeByIds(idList);
    }


    @Override
    public Page<Period> periodPage(Page<Period> page, QueryWrapper<Period> queryWrapper){
        return periodMapper.selectPage(page,queryWrapper);
    }

    @Override
    @Scheduled(cron = "0 0/1 * * * ? ")
    public void sendRemindMsgToUser() {
        String useRemind = configMapper.selectOne(new QueryWrapper<SysConfig>().lambda().eq(SysConfig::getCode,"USE_PERIOD_REMIND")).getValue();
        if(useRemind.equals("1")){
            //每分钟执行一次
            log.info("定时任务开始:sendRemindMsgToUser,开始时间:"+LocalDateTimeUtil.parse(LocalDateTime.now()));

            LocalDateTime now = LocalDateTime.now();
            //获取间隔时间
            String remindMin = configMapper.selectOne(new QueryWrapper<SysConfig>().lambda().eq(SysConfig::getCode,"PERIOD_REMIND_TIME")).getValue();
            LocalDateTime remindTime = LocalDateTimeUtil.plus(now, Integer.parseInt(remindMin), ChronoUnit.MINUTES);

            String remindTimeString = LocalDateTimeUtil.parse(remindTime);

            //查询提醒时间的课程
            LambdaQueryWrapper<Period> qw = new QueryWrapper<Period>().lambda().eq(Period::getStartTime,remindTimeString);
            List<Period> periodList = periodMapper.selectList(qw);
            if(!CollectionUtils.isEmpty(periodList)){
                //从缓存获取token，获取不到请求token并放入缓存
                String token =(String) redisTemplate.opsForValue().get("WxCache:AccessToken");
                if(StringUtils.isEmpty(token)){
                    JSONObject tokenObj  = WechatUtil.getAccessToken();
                    token = tokenObj.getString("access_token");
                    String expires = tokenObj.getString("expires_in");
                    if(!StringUtils.isEmpty(token)){
                        redisTemplate.opsForValue().set("WxCache:AccessToken",token, Integer.parseInt(expires),TimeUnit.SECONDS);
                    }else{
                        log.error("获取token错误"+tokenObj);
                    }
                }

                String AccessToken = token;
                periodList.forEach(period -> {
                    //获取发送openId列表
                    List<String> openIdList  = periodMapper.getOpenIdListByPeriodId(period.getId());
                    openIdList.forEach(openId->{
                        //组装参数并发送消息
                        JSONObject data = new JSONObject();
                        data.put("first",new WxMsgTemplateData("上课提醒:"));
                        data.put("keyword1",new WxMsgTemplateData(period.getStartTime()));
                        data.put("keyword2",new WxMsgTemplateData(period.getAddress()));
                        data.put("remark",new WxMsgTemplateData("记得上课哦"));
                        //todo 修改小程序跳转路径
                        WechatUtil.sendUniformMessage(AccessToken,openId,"YKOomDrQtcm5HllnfO-Pvne5O6TFI_RP4LP7mkp5Ucw",data,"/index");

                    });

                });
            }
            log.info("定时任务结束:sendRemindMsgToUser,结束时间:"+LocalDateTimeUtil.parse(LocalDateTime.now()));
        }
    }

    @Override
    public void studentBindPeriod(String studentId, String periodId) {
        periodMapper.addPeriodStudent(studentId, periodId);
    }

    private void courseCacheClear(String periodId){
        String key = "Service:CourseService:id::";
        List<String> courseIdList = courseMapper.getCourseIdListByPeriodId(periodId);
        Set<String> idsKeys = new HashSet<>();
        courseIdList.forEach(courseId->{
            String idKey = key+courseId;
            idsKeys.add(idKey);
        });
        redisTemplate.delete(idsKeys);
    }
}
